package com.xcmg.xiot.Utils;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.*;


public class DataBase {
    private static Logger logger = LoggerFactory.getLogger(DataBase.class);

    /**
     * 数据源对象
     */
    private ComboPooledDataSource _ds = null;
    /**
     * 单例实体对象
     */
    private static DataBase instance = null;

    /**
     * jdbc驱动名
     */
    private static String _driverClass = "oracle.jdbc.driver.OracleDriver";

    /**
     * oracle服务信息
     */
    private static String _jdbcUrl = "jdbc:oracle:thin:@10.80.0.81:1521:xgdb";

    /**
     * oracle用户名
     */
    private static String _user = "XGIT";

    /**
     * oracle密码
     */
    private static String _password = "XGIT";

    /**
     * 线程池初台化大小
     */
    private static int initPoolSize = 2;

    /**
     * 线程池最小值限制
     */
    private static int minPoolSize = 2;

    /**
     * 线程池每次增长量
     */
    private static int acquireIncrement = 1;

    /**
     * 线程池最大值限制
     */
    private static int maxPoolSize = 6;

    /**
     * false则数据库断线后重连
     */
    private static boolean isBreakAfterAcquireFailure = false;

    /**
     * 帮助线程数
     */
    private static int helpThreadNum = 6;

    /**
     * 重连次数
     */
    private static int acquireRetryAttempts = 10;

    /**
     * 重连时间间隔
     */
    private static int acquireRetryDelay = 1000;

    /**
     * 数据库连接池构造函数
     */
    private DataBase() {
        try {
            _ds = new ComboPooledDataSource();
            _ds.setDriverClass(_driverClass);
            _ds.setJdbcUrl(_jdbcUrl);
            _ds.setUser(_user);
            _ds.setPassword(_password);
            _ds.setBreakAfterAcquireFailure(isBreakAfterAcquireFailure);
            _ds.setInitialPoolSize(initPoolSize);
            _ds.setMinPoolSize(minPoolSize);
            _ds.setAcquireIncrement(acquireIncrement);
            _ds.setMaxPoolSize(maxPoolSize);
            _ds.setNumHelperThreads(helpThreadNum);
            _ds.setAcquireRetryAttempts(acquireRetryAttempts);
            _ds.setAcquireRetryDelay(acquireRetryDelay);
        } catch (Exception e) {
            logger.error("创建数据库操作对象失败", e);
            instance = null;
        }
    };

    /**
     * 初始化配置信息
     *
     *            数据库配置信息
     * @return
     */
    public static void init(String driver, String jdbcUrl,
                            String user, String password) {

        _driverClass = driver;
        _jdbcUrl = jdbcUrl;
        _user = user;
        _password = password;
        try {
            DataBase.attempClose(DataBase.getInstance().getConnection());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取数据库操作实体对象
     *
     * @return
     * @throws Exception
     */
    public static DataBase getInstance() throws Exception {
        if (instance == null) {
            instance = new DataBase();
        }
        return instance;
    }

    /**
     * 数据库连接池(拷贝)
     */
    public static Connection initConnection(String user, String password)  {

        Connection connection = null;
        try {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(_driverClass);
            ds.setJdbcUrl(_jdbcUrl);
            ds.setUser(user);
            ds.setPassword(password);
            ds.setBreakAfterAcquireFailure(isBreakAfterAcquireFailure);
            ds.setInitialPoolSize(initPoolSize);
            ds.setMinPoolSize(minPoolSize);
            ds.setAcquireIncrement(acquireIncrement);
            ds.setMaxPoolSize(maxPoolSize);
            ds.setNumHelperThreads(helpThreadNum);
            ds.setAcquireRetryAttempts(acquireRetryAttempts);
            ds.setAcquireRetryDelay(acquireRetryDelay);

            connection = ds.getConnection();
        } catch (Exception e) {
            logger.error("创建数据库操作对象失败", e);
            instance = null;
        }

        return connection;
    }

    /**
     * 获取数据库连接对象
     *
     * @return
     * @throws java.sql.SQLException
     */
    public Connection getConnection() throws SQLException {
        return this._ds.getConnection();
    }

    /**
     * 关闭连接
     *
     * @param con
     */
    public static void attempClose(Connection con) {
        if (con != null) {
            try {
                con.close();
                con = null;
            } catch (SQLException e) {
                logger.error("close connection error: " + con, e);
            }
        }
    }

    /**
     * 判断PreparedStatement
     *
     * @param pstmt
     */
    public static void attempClose(PreparedStatement pstmt) {
        if (pstmt != null) {
            try {
                pstmt.close();
                pstmt = null;
            } catch (SQLException e) {
                logger.error("close PreparedStatement error: " + pstmt, e);
            }
        }
    }

    /**
     * 关闭ResultSet
     *
     * @param rs
     */
    public static void attempClose(ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
                rs = null;
            } catch (SQLException e) {
                logger.error("close ResultSet error: " + rs, e);
            }
        }
    }

    /**
     * 判断Statement
     *
     * @param stmt
     */
    public static void attempClose(Statement stmt) {
        if (stmt != null) {
            try {
                stmt.close();
                stmt = null;
            } catch (SQLException e) {
                logger.error("close Statement error: " + stmt, e);
            }
        }
    }


}
